package com.chinaisafe.common.config;

import com.chinaisafe.base.common.enums.AnswerCodeEnum;
import com.chinaisafe.base.common.exception.BizException;
import com.chinaisafe.base.common.vo.Answer;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.BindingResult;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.servlet.NoHandlerFoundException;

import java.util.Map;

/**
 * GlobalExceptionHandlerConfig
 * Description：全局异常拦截
 *
 * @author JiangZhaoYong
 * @date 2024/7/10 17:37
 */
@ControllerAdvice
@Slf4j
public class GlobalExceptionHandlerConfig {

    /**
     * 全局异常拦截
     *
     * @param e                  异常
     * @param httpServletRequest 请求信息
     * @return Answer<Void> 响应
     * @author JiangZhaoYong
     * @date 2024/7/11 17:39
     */
    @ResponseBody
    @org.springframework.web.bind.annotation.ExceptionHandler(value = Exception.class)
    public Answer<Void> exceptionHandler(Exception e, HttpServletRequest httpServletRequest) {
        log.error("========================捕获服务器异常开始==========================");
        if (httpServletRequest != null) {
            log.error("请求方式: " + httpServletRequest.getMethod());
            log.error("请求的接口: " + httpServletRequest.getRequestURI());
            log.error("完整的请求URL: " + httpServletRequest.getRequestURL());
            log.error("请求的LocalAddr: " + httpServletRequest.getLocalAddr());
            log.error("请求的RemoteAddr: " + httpServletRequest.getRemoteAddr());
            StringBuilder paramStr = getStringBuilder(httpServletRequest);
            log.info(paramStr.toString());
        }
        log.error("异常信息：" + e.getMessage(), e);
        log.error("========================捕获服务器异常结束==========================");
        return Answer.create(AnswerCodeEnum.EXCEPTION, AnswerCodeEnum.EXCEPTION.getMessage(), null);
    }

    /**
     * 自定义业务异常拦截
     *
     * @param e                  异常
     * @param httpServletRequest 请求信息
     * @return Answer<Void> 响应
     * @author JiangZhaoYong
     * @date 2024/7/11 16:17
     */
    @ResponseBody
    @org.springframework.web.bind.annotation.ExceptionHandler(value = BizException.class)
    public Answer<Void> exceptionHandler(BizException e, HttpServletRequest httpServletRequest) {
        log.error("========================捕获自定义异常开始==========================");
        if (httpServletRequest != null) {
            log.error("请求方式：{}", httpServletRequest.getMethod());
            log.error("请求的接口：{}", httpServletRequest.getRequestURI());
            log.error("完整的请求URL：{}", httpServletRequest.getRequestURL());
            log.error("请求的LocalAddr：{}", httpServletRequest.getLocalAddr());
            StringBuilder paramStr = getStringBuilder(httpServletRequest);
            log.error(paramStr.toString());
        }
        log.error("异常信息：" + e.getMessage(), e);
        log.error("========================捕获自定义异常结束==========================");
        return Answer.create(e.getCode(), e.getMessage(), null);
    }

    /**
     * 获取请求参数
     *
     * @param httpServletRequest 请求信息
     * @return StringBuilder 参数拼接
     * @author JiangZhaoYong
     * @date 2024/7/11 16:51
     */
    private static StringBuilder getStringBuilder(HttpServletRequest httpServletRequest) {
        Map<String, String[]> parameterMap = httpServletRequest.getParameterMap();
        StringBuilder paramStr = new StringBuilder("请求的参数为：");
        for (String paramName : parameterMap.keySet()) {
            String[] paramNames = parameterMap.get(paramName);
            if (paramNames.length > 0) {
                paramStr.append(paramName).append(" = ").append(paramNames[0]).append("&");
            }
        }
        return paramStr;
    }

    /**
     * 捕获数据校验异常
     *
     * @param e                  异常
     * @param httpServletRequest 请求信息
     * @param result             异常绑定结果
     * @return Answer<Void> 响应
     * @author JiangZhaoYong
     * @date 2024/7/11 17:40
     */
    @ResponseBody
    @org.springframework.web.bind.annotation.ExceptionHandler(value = org.springframework.web.bind.MethodArgumentNotValidException.class)
    public Answer<Void> exceptionHandler(org.springframework.web.bind.MethodArgumentNotValidException e, HttpServletRequest httpServletRequest, BindingResult result) {
        log.error("========================捕获数据校验异常开始==========================");
        String defaultMessage = "数据参数错误";
        if (httpServletRequest != null) {
            log.error("请求方式: " + httpServletRequest.getMethod());
            log.error("请求的接口: " + httpServletRequest.getRequestURI());
            log.error("完整的请求URL: " + httpServletRequest.getRequestURL());
            log.error("请求的LocalAddr: " + httpServletRequest.getLocalAddr());
            StringBuilder paramStr = getStringBuilder(httpServletRequest);
            log.error(paramStr.toString());
            if (result != null && result.getFieldError() != null) {
                log.error("出现错误的字段：{}，报错信息：{}", result.getFieldError().getField(), result.getFieldError().getDefaultMessage());
                defaultMessage = result.getFieldError().getDefaultMessage();
            }
        }
        log.error("异常信息：" + e.getMessage(), e);
        log.error("========================捕获数据校验异常结束结束==========================");
        return Answer.create(AnswerCodeEnum.FAIL, defaultMessage, null);
    }

    /**
     * 捕获文件上传超限异常
     *
     * @param e 异常
     * @return Answer<Void> 响应
     * @author JiangZhaoYong
     * @date 2024/7/11 17:41
     */
    @ResponseBody
    @org.springframework.web.bind.annotation.ExceptionHandler(value = MaxUploadSizeExceededException.class)
    public Answer<Void> exceptionHandler(MaxUploadSizeExceededException e) {
        log.error("======================捕获文件上传超出限制异常开始==========================");
        log.error("异常信息：" + e.getMessage(), e);
        log.error("======================捕获文件上传超出限制异常结束==========================");
        return Answer.create(AnswerCodeEnum.FAIL, "文件大小超出限制", null);
    }

    /**
     * 捕获资源未找到异常
     *
     * @param e 异常
     * @return Answer<String> 响应
     * @author JiangZhaoYong
     * @date 2024/7/11 17:43
     */
    @org.springframework.web.bind.annotation.ExceptionHandler(NoHandlerFoundException.class)
    @ResponseBody
    public Answer<String> handlerNoFoundException(Exception e) {
        log.error("=========================捕获资源未找到异常开始===========================");
        log.error("异常信息：" + e.getMessage(), e);
        log.error("=========================捕获资源未找到异常结束===========================");
        return Answer.create(AnswerCodeEnum.NOT_FOUND, AnswerCodeEnum.NOT_FOUND.getMessage(), null);
    }

    /**
     * 捕获请求方式不支持异常
     *
     * @param e 异常
     * @return Answer<String> 响应
     * @author JiangZhaoYong
     * @date 2024/7/11 17:44
     */
    @org.springframework.web.bind.annotation.ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    @ResponseBody
    public Answer<String> handlerMethodNotSupportedException(Exception e) {
        log.error("========================捕获请求方式不支持异常开始==========================");
        log.error("异常信息：" + e.getMessage(), e);
        log.error("=========================捕获请求方式不支持异常结束===========================");
        return Answer.create(AnswerCodeEnum.NOT_FOUND, AnswerCodeEnum.NOT_FOUND.getMessage(), null);
    }
}
